﻿// Copyright 2012 Jack Bulan (agentgeo)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
using System.Threading;

using GemWorkshop.Hex;
using GemWorkshop.Formats.Nitro;
using GemWorkshop.Text;
using GemWorkshop.Map;
using GemWorkshop.Pokemon;
using GemWorkshop.Pokedex;
using GemWorkshop.Trainer;
using GemWorkshop.Formats;

namespace GemWorkshop
{
    public partial class Form1 : Form
    {
        public static IniFile GameSettings;
        public static string Game;
        public static string GameDirectory;
        
        string romPath;//, tempPath;
        ROMUnpacker romUnpacker;

        public Form1()
        {
            InitializeComponent();
            tabControl1.Enabled = false;

            GameSettings = new IniFile(Environment.CurrentDirectory + "\\Games.ini");
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            // Delete the file directory.
            /*
            if (Directory.Exists(tempPath))
            {
                Directory.Delete(tempPath, true);
            }
            */
            // Do we want this???
        }

        #region Loading

        private void mnuLoad_Click(object sender, EventArgs e)
        {
            try
            {
                open.FileName = "";
                open.Title = "Load a ROM...";
                open.Filter = "Pokémon ROMs|*.nds";

                if (open.ShowDialog() != DialogResult.OK) return;

                this.Cursor = Cursors.WaitCursor;
                Application.DoEvents();

                Stopwatch stop = Stopwatch.StartNew();

                this.Text = "Gem Workshop - " +
                    Path.GetFileName(open.FileName);
                romPath = open.FileName;
                GameDirectory = Environment.CurrentDirectory +
                        @"\temp_" +
                        Path.GetFileNameWithoutExtension(romPath);

                // Extract files!
                romUnpacker = new ROMUnpacker();
                TimeSpan timeTaken = romUnpacker.DoRom(romPath, GameDirectory);

                //this.Text += " - Loaded in: " + timeTaken.TotalMilliseconds.ToString();
                lblLoadTime.Text = "Extracted in: " +
                    timeTaken.TotalSeconds.ToString() + "s";

                // Show the files we have in out tree view.
                ShowFiles();

                // Display our header information
                pIcon.Image = romUnpacker.Banner.Image;
                listInfo.Items[0].SubItems[2].Text = romUnpacker.Header.Title;
                listInfo.Items[1].SubItems[2].Text = romUnpacker.Header.Code;
                listInfo.Items[2].SubItems[2].Text = romUnpacker.Header.Maker;
                listInfo.Items[3].SubItems[2].Text = romUnpacker.Header.DeviceCode.ToString();
                listInfo.Items[4].SubItems[2].Text = (romUnpacker.Header.FileLength * 14).ToString() + " MB";
                listInfo.Items[5].SubItems[2].Text = romUnpacker.Header.Version.ToString();
                listInfo.Items[6].SubItems[2].Text = romUnpacker.Header.InternalFlags.ToString();
                listInfo.Items[7].SubItems[2].Text = "0x" + romUnpacker.Header.Arm9Offset.ToString("X");
                listInfo.Items[8].SubItems[2].Text = "0x" + romUnpacker.Header.Arm9Entry.ToString("X");
                listInfo.Items[9].SubItems[2].Text = "0x" + romUnpacker.Header.Arm9Load.ToString("X");
                listInfo.Items[10].SubItems[2].Text = "0x" + romUnpacker.Header.Arm9Length.ToString("X") + " bytes";
                listInfo.Items[11].SubItems[2].Text = "0x" + romUnpacker.Header.Arm7Offset.ToString("X");
                listInfo.Items[12].SubItems[2].Text = "0x" + romUnpacker.Header.Arm7Entry.ToString("X");
                listInfo.Items[13].SubItems[2].Text = "0x" + romUnpacker.Header.Arm7Load.ToString("X");
                listInfo.Items[14].SubItems[2].Text = "0x" + romUnpacker.Header.Arm7Length.ToString("X") + " bytes";

                // ...
                Game = romUnpacker.Header.Code;

                tabControl1.Enabled = true;

                stop.Stop();
                lblLoadTime.Text += "\nLoaded in: " +
                    stop.Elapsed.TotalSeconds.ToString() + "s"; ;

                this.Cursor = Cursors.Default;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void ShowFiles()
        {
            // Show in treeview
            treeFiles.Nodes.Clear();
            DirectoryInfo dirInfo = new DirectoryInfo(GameDirectory);
            DirectoryInfo[] children = dirInfo.GetDirectories();
            FileInfo[] mainFiles = dirInfo.GetFiles();

            foreach (DirectoryInfo dir in children)
            {
                treeFiles.Nodes.Add(ReadDirectory(dir));
            }

            foreach (FileInfo f in mainFiles)
            {
                treeFiles.Nodes.Add(f.Name, f.Name, 1, 1);
            }
        }

        // Allows for recursive looking through of a directory...
        private TreeNode ReadDirectory(DirectoryInfo dir)
        {
            TreeNode root = new TreeNode();
            root.Name = dir.Name;
            root.Text = dir.Name;
            root.ImageIndex = 0;
            root.SelectedImageIndex = 0;

            FileInfo[] files = dir.GetFiles();
            if (files != null && files.Length > 0)
            {
                foreach (FileInfo f in files)
                {
                    TreeNode fNode = new TreeNode();
                    fNode.Name = f.Name;
                    fNode.Text = f.Name;
                    //fNode.ImageIndex = 1;
                    //fNode.SelectedImageIndex = 1;

                    switch (f.Extension.ToLower())
                    {
                        case ".dat":
                        case ".bin":
                            fNode.ImageIndex = 1;
                            fNode.SelectedImageIndex = 1;
                            break;
                        case ".txt":
                            fNode.ImageIndex = 2;
                            fNode.SelectedImageIndex = 2;
                            break;
                        case ".sdat":
                            fNode.ImageIndex = 3;
                            fNode.SelectedImageIndex = 3;
                            break;
                        case ".narc":
                            fNode.ImageIndex = 4;
                            fNode.SelectedImageIndex = 4;
                            break;
                        case ".nclr":
                            fNode.ImageIndex = 5;
                            fNode.SelectedImageIndex = 5;
                            break;
                        case ".ncgr":
                            fNode.ImageIndex = 6;
                            fNode.SelectedImageIndex = 6;
                            break;
                        case ".nscr":
                            fNode.ImageIndex = 7;
                            fNode.SelectedImageIndex = 7;
                            break;
                        case ".nsbmd":
                            fNode.ImageIndex = 9;
                            fNode.SelectedImageIndex = 9;
                            break;
                        case ".nsbtx":
                            fNode.ImageIndex = 10;
                            fNode.SelectedImageIndex = 10;
                            break;

                        default:
                            fNode.ImageIndex = 8;
                            fNode.SelectedImageIndex = 8;
                            break;
                    }

                    root.Nodes.Add(fNode);
                }
            }

            DirectoryInfo[] children = dir.GetDirectories();
            if (children != null &&
                children.Length > 0)
            {
                foreach (DirectoryInfo cDir in children)
                {
                    root.Nodes.Add(ReadDirectory(cDir));
                }
            }

            return root;
        }

        #endregion

        #region Saving

        private void mnuWrite_Click(object sender, EventArgs e)
        {
            try
            {
                ROMRepacker romRepacker = new ROMRepacker();
                TimeSpan timeTaken = romRepacker.DoRom(romUnpacker);

                MessageBox.Show("Game written!"+
                    "\nRepacked in: " + timeTaken.TotalSeconds.ToString() + "s");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        #endregion

        private void mnuExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        #region Tools

        private void bMapEdit_Click(object sender, EventArgs e)
        {
            //MapEditor mapEd = new MapEditor();
            //mapEd.ShowDialog();
            MapSelector mapSel = new MapSelector();
            mapSel.ShowDialog();
        }

        private void bTextEdit_Click(object sender, EventArgs e)
        {
            TextEditor textEd = new TextEditor();
            textEd.ShowDialog();
        }

        private void bPokeEdit_Click(object sender, EventArgs e)
        {
            PokeEditor pokeEd = new PokeEditor();
            pokeEd.ShowDialog();
        }
            
        private void bDexOrderEdit_Click(object sender, EventArgs e)
        {
            DexOrderEditor dexEd = new DexOrderEditor();
            dexEd.ShowDialog();
        }

        private void bTrainerEdit_Click(object sender, EventArgs e)
        {
            TrainerEditor trainerEd = new TrainerEditor();
            trainerEd.ShowDialog();
        }

        #endregion

        private void bHexEd_Click(object sender, EventArgs e)
        {
            string name = treeFiles.SelectedNode.Text;
            string path;
            if (treeFiles.SelectedNode.Parent != null)
            {
                if (treeFiles.SelectedNode.Parent.Text == "overlay")
                {
                    path = GameDirectory + "\\overlay\\" + name;
                }
                else
                {
                    // File in folders
                    ushort id = romUnpacker.NameTable.IDs[name];
                    ushort num = romUnpacker.FileNumbers[id];
                    path = romUnpacker.FilePaths[num];
                    //MessageBox.Show(path);
                }
            }
            else
            {
                path = GameDirectory + "\\" + name;
            }
            //MessageBox.Show(name);

            HexEditor hex = new HexEditor(path);
            hex.ShowDialog();
        }

    }
}
